package avoidDeadLock;

import java.util.ArrayList;
import java.util.List;

/**
 * 改进版,用wait-notify替代while循环
 */
public class AllocatorPlusDemo {

    public static void main(String[] args) {
        Allocator allocator = new Allocator();
        Account from = new Account(200);
        Account to = new Account(200);
        // 申请资源
        allocator.apply(from, to);

        from.transfer(to, 10);

        // 释放资源
        allocator.free(from, to);
    }

    static class Allocator {
        private List<Object> als = new ArrayList<>();

        public synchronized void apply(Object from, Object to) {
            while (als.contains(from) || als.contains(to)) {
                try {
                    // 当前线程挂起，加入等待队列
                    wait();
                } catch (InterruptedException e) {
                }
            }
            als.add(from);
            als.add(to);
        }

        // 归还资源
        public synchronized void free(Object from, Object to) {
            als.remove(from);
            als.remove(to);
            // 唤醒等待线程，达到的效果是: wait队列里的线程被移入就绪队列
            notifyAll();
        }
    }

    static class Account {
        private long balance;

        public Account(long balance) {
            if (balance < 0) {
                throw new IllegalArgumentException("balance必须非负数");
            }
            this.balance = balance;
        }

        public void transfer(Account target, long amount) {

            if (balance > amount) {
                balance -=  amount;
                target.balance += amount;
            }
        }
    }
}


